import 'package:built_collection/built_collection.dart';
import 'package:backend.core/core/domain/entities/api/web/api_web_one_time_purchased_item.dart';
import 'package:backend.core/core/domain/entities/api/web/api_web_one_time_purchased_item_transaction.dart';
import 'package:backend.core/core/domain/entities/api/web/api_web_purchased_item.dart';
import 'package:backend.core/core/domain/entities/web/web_one_time_purchased_item_transaction.dart';
import 'package:backend.core/core/domain/entities/web/web_purchase_item.dart';
import 'package:backend.core/core/domain/entities/web/web_purchased_subscription_info.dart';
import 'package:backend.core/core/domain/entities/web/web_purchased_subscription_transaction.dart';
import 'package:backend.core/core/domain/entities/web/web_subscription.dart';
import 'package:backend.core/core/domain/entities/web/web_transaction.dart';
import 'package:backend.core/core/domain/entities/web/yookassa/yookassa_one_time_purchased_item_transaction.dart';
import 'package:backend.purchases/domain/helpers/api/web/create_api_web_purchased_subscription_from_internal_one.dart';
import 'package:backend.purchases/domain/helpers/api/web/yookassa/create_api_yookassa_one_time_purchased_item_transaction_from_internal_one.dart';

abstract class CreateApiWebPurchasedItemsFromInternalOnes {
  BuiltList<ApiWebPurchasedItem> call({
    required BuiltList<WebTransaction> transactions,
    required BuiltList<WebPurchasedSubscriptionInfo> purchasedSubscriptionInfos,
    required BuiltMap<String, WebPurchaseItem> purchaseItemMap,
  });
}

class CreateApiWebPurchasedItemsFromInternalOnesImpl
    implements CreateApiWebPurchasedItemsFromInternalOnes {
  const CreateApiWebPurchasedItemsFromInternalOnesImpl({
    required CreateApiYookassaOneTimePurchasedItemTransactionFromInternalOne
        createApiYookassaOneTimePurchasedItemTransactionFromInternalOne,
    required CreateApiWebPurchasedSubscriptionFromInternalOne
        createApiWebPurchasedSubscriptionFromInternalOne,
  })  : _createApiYookassaOneTimePurchasedItemTransactionFromInternalOne =
            createApiYookassaOneTimePurchasedItemTransactionFromInternalOne,
        _createApiWebPurchasedSubscriptionFromInternalOne =
            createApiWebPurchasedSubscriptionFromInternalOne;

  final CreateApiYookassaOneTimePurchasedItemTransactionFromInternalOne
      _createApiYookassaOneTimePurchasedItemTransactionFromInternalOne;
  final CreateApiWebPurchasedSubscriptionFromInternalOne
      _createApiWebPurchasedSubscriptionFromInternalOne;

  @override
  BuiltList<ApiWebPurchasedItem> call({
    required BuiltList<WebTransaction> transactions,
    required BuiltList<WebPurchasedSubscriptionInfo> purchasedSubscriptionInfos,
    required BuiltMap<String, WebPurchaseItem> purchaseItemMap,
  }) {
    final apiPurchasedItems = <ApiWebPurchasedItem>[];
    final purchasedSubscriptionTransactionMap =
        <String, List<WebPurchasedSubscriptionTransaction>>{};

    for (final transaction in transactions) {
      if (transaction is WebOneTimePurchasedItemTransaction) {
        late final ApiWebOneTimePurchasedItemTransaction apiTransaction;

        if (transaction is YookassaOneTimePurchasedItemTransaction) {
          apiTransaction = _createApiYookassaOneTimePurchasedItemTransactionFromInternalOne(
            transaction: transaction,
          );
        }

        final purchasedItem = ApiWebOneTimePurchasedItem(
          purchaseItemSku: transaction.purchaseItemSku,
          test: transaction.test,
          transactionId: transaction.id,
          revoked: transaction.revoked,
          transaction: apiTransaction,
        );

        apiPurchasedItems.add(purchasedItem);
      } else if (transaction is WebPurchasedSubscriptionTransaction) {
        purchasedSubscriptionTransactionMap[transaction.originalTransactionId] ??= [];
        purchasedSubscriptionTransactionMap[transaction.originalTransactionId]!.add(transaction);
      }
    }

    for (final purchasedSubscriptionInfo in purchasedSubscriptionInfos) {
      final transactions =
          purchasedSubscriptionTransactionMap[purchasedSubscriptionInfo.originalTransactionId]!;

      final subscription =
          purchaseItemMap[purchasedSubscriptionInfo.purchaseItemSku] as WebSubscription;

      final apiPurchasedSubscription = _createApiWebPurchasedSubscriptionFromInternalOne(
        transactions: transactions.toBuiltList(),
        purchasedSubscriptionInfo: purchasedSubscriptionInfo,
        subscriptionDuration: subscription.duration,
      );

      apiPurchasedItems.add(apiPurchasedSubscription);
    }

    return apiPurchasedItems.toBuiltList();
  }
}
